#pragma once
#include "Buffer.hpp"
#include "Socket.hpp"
#include "Channel.hpp"
#include "Poller.hpp"
#include "TimeWheel.hpp"
#include "EventLoop.hpp"
#include "LoopThread.hpp"
#include "LoopThreadPool.hpp"
#include "Connection.hpp"
#include "Acceptor.hpp"

class TCPServer
{
private:
    uint64_t _next_id; // 新连接id，自增
    uint16_t _port;
    int _timeout;                  // 非活跃连接销毁时间
    bool _enable_inactive_release; // 是否启动非活跃连接销毁
    EventLoop _baseloop;
    Acceptor _acceptor;
    LoopThreadPool _pool;
    std::unordered_map<uint64_t, PtrConnection> _conns;

    using ConnectedCallback = std::function<void(const PtrConnection &)>;
    using MessageCallback = std::function<void(const PtrConnection &, Buffer *)>;
    using ClosedCallback = std::function<void(const PtrConnection &)>;
    using AnyEventCallback = std::function<void(const PtrConnection &)>;
    ConnectedCallback _connected_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    AnyEventCallback _event_callback;

    // 为新连接构造connection
    void NewConnection(int fd)
    {
        std::cout << "Connection thread id: " << std::this_thread::get_id() << std::endl;
        PtrConnection conn(new Connection(_next_id, fd, _pool.NextLoop()));
        conn->SetMessageCallback(_message_callback);
        conn->SetConnectedCallback(_connected_callback);
        conn->SetClosedCallback(_closed_callback);
        conn->SetSrvClosedCallback(std::bind(&TCPServer::RemoveConnection, this, std::placeholders::_1));
        if (_enable_inactive_release)
            conn->EnableInactiveRelease(_timeout);
        conn->Established();
        _conns.insert(std::make_pair(_next_id, conn));
        _next_id++;
    }

    void RunAfterInLoop(const Functor &task, int delay)
    {
        _baseloop.TimerAdd(_next_id, task, delay);
        ++_next_id;
    }

    void RemoveConnectionInLoop(const PtrConnection &conn)
    {
        int id = conn->Id();
        auto it = _conns.find(id);
        if (it != _conns.end())
            _conns.erase(it);
    }

    void RemoveConnection(const PtrConnection &conn)
    {
        _baseloop.RunInLoop(std::bind(&TCPServer::RemoveConnectionInLoop, this, conn));
    }

public:
    TCPServer(uint16_t port) : _next_id(0), _port(port), _enable_inactive_release(false),
                               _acceptor(&_baseloop, _port), _pool(&_baseloop)
    {
        _acceptor.SetAcceptCallback(std::bind(&TCPServer::NewConnection, this, std::placeholders::_1));
        _acceptor.Listen();
    }
    ~TCPServer() {}
    // 设置线程池线程数量
    void SetThreadCount(int num) { _pool.SetThreadCount(num); }
    // 回调函数设置
    void SetConnectedCallback(const ConnectedCallback &cb) { _connected_callback = cb; }
    void SetMessageCallback(const MessageCallback &cb) { _message_callback = cb; }
    void SetClosedCallback(const ClosedCallback &cb) { _closed_callback = cb; }
    void SetAnyEventCallback(const AnyEventCallback &cb) { _event_callback = cb; }
    // 设置连接超时销毁
    void EnableInactiveRelease(int sec)
    {
        _timeout = sec;
        _enable_inactive_release = true;
    }
    // 设置定时任务
    void RunAfter(const Functor &task, int delay)
    {
        _baseloop.RunInLoop(std::bind(&TCPServer::RunAfterInLoop, this, task, delay));
    }
    void Start()
    {
        _pool.Create();
        _baseloop.Start();
    }
};

void Channel::Update() { _loop->UpdateEvent(this); }
void Channel::Remove() { _loop->RemoveEvent(this); }

// 添加任务
void TimeWheel::TimerAdd(uint64_t id, const TaskFunc &task, uint32_t delay)
{
    _loop->RunInLoop(std::bind(&TimeWheel::TimerAddInLoop, this, id, task, delay));
}
// 刷新任务
void TimeWheel::TimerRefresh(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimeWheel::TimerRefreshInLoop, this, id));
}
// 取消任务
void TimeWheel::TimerCancal(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimeWheel::TimerCancalInLoop, this, id));
}